﻿using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;

namespace GrpcCommon.Helpers
{
    public class JwtHelper
    {
        /// <summary>
        /// 颁发JWT Token
        /// </summary>
        /// <param name="securityKey"></param>
        /// <param name="accountName"></param>
        /// <returns></returns>
        public static string GenerateJwt(string securityKey, string accountName)
        {
            var claims = new List<Claim>
            {
                new Claim("userid", accountName)
            };

            //秘钥 (SymmetricSecurityKey 对安全性的要求，密钥的长度太短会报出异常)
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(securityKey));
            var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            var jwt = new JwtSecurityToken(
                issuer: "https://ifcloud.com/zerotrust",
                claims: claims,
                expires: DateTime.Now.AddMinutes(1),
                signingCredentials: credentials);
            var jwtHandler = new JwtSecurityTokenHandler();
            var encodedJwt = jwtHandler.WriteToken(jwt);
            return encodedJwt;
        }

        /// <summary>
        /// 解析
        /// </summary>
        /// <param name="token"></param>
        /// <param name="securityKey"></param>
        /// <returns></returns>
        public static Tuple<bool, string> ValidateJwt(string token, string securityKey)
        {
            try
            {
                //对称秘钥
                SecurityKey key = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(securityKey));
                //校验token
                var validateParameter = new TokenValidationParameters()
                {
                    ValidateAudience = false,
                    ValidIssuer = "https://ifcloud.com/zerotrust",
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = key,
                    ClockSkew = TimeSpan.Zero//校验过期时间必须加此属性
                };
                var jwtToken = new JwtSecurityTokenHandler().ValidateToken(token, validateParameter, out _);
                var claimDic = new Dictionary<string, string>();

                foreach (var claim in jwtToken.Claims)
                {
                    claimDic.TryAdd(claim.Type, claim.Value);
                }

                var payLoad = JsonConvert.SerializeObject(claimDic);

                return new Tuple<bool, string>(true, payLoad);
            }
            catch (SecurityTokenExpiredException expired)
            {
                //token过期
                return new Tuple<bool, string>(false, expired.Message);
            }
            catch (SecurityTokenNoExpirationException noExpiration)
            {
                //token未设置过期时间
                return new Tuple<bool, string>(false, noExpiration.Message);
            }
            catch (SecurityTokenException tokenEx)
            {
                //表示token错误
                return new Tuple<bool, string>(false, tokenEx.Message);
            }
            catch (Exception err)
            {
                // 解析出错
                Console.WriteLine(err.StackTrace);
                return new Tuple<bool, string>(false, err.Message);
            }
        }
    }
}
